﻿/***********************************************************************************************
 * 
 * ProjectName: WMSSoft.WinKStart
 * 
 * Description: Panel to use in Startmenus Program Page
 * 
 * Created:     14.11.2012
 * 
 * Author:      matthias wagler - matthias@WMSSoft.de
 * 
 * Copyright:   Copyright 2012 by WMSSoft.de
 * 
 * License:     GPLv3
 * 
 * History:     14.11.2012 - matthias wagler matthias@WMSSoft.de   -   Created
 * 
 **********************************************************************************************/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using WMSSoft.Lib.Basic;
using WMSSoft.Lib.WinKStart;
using WMSSoft.WinKStart.Lib;
using WMSSoft.Lib.Enums;

namespace WMSSoft.WinKStart
{
    /// <summary>
    /// Interaktionslogik für StartmenuLIst.xaml
    /// </summary>
    public partial class ucStartmenuPrograms : UserControl
    {
        private cStartmenuReader m_StartMenuReader = null;
        private cStartmenuItem m_RootStartMenuItem = null;
        private ItemRenderer m_StartMenuRenderer = null;
        private cStartmenuItem m_ProgramStartMenuItem = null;
        private cStartmenuItem m_CurrentRootItem = null;
        private cStartmenuItem m_SearchResult = null;
        private List<cStartmenuItem> m_BreadCrumbItems = new List<cStartmenuItem>();
        private Dictionary<int, cStartmenuItem> m_CurrentVisibleProgrammItems = null;
        private BackgroundWorker m_StartMenuItemsBackgroundReaderThread = null;
        private System.Windows.Threading.DispatcherTimer m_Timer = new System.Windows.Threading.DispatcherTimer();
        private bool _CanSelectStartMenuItem = true;
        public event WMSSoft.Lib.Shell.FavoriteEventArgs AddFavorite;
        

        public ucStartmenuPrograms()
        {
            InitializeComponent();

            m_StartMenuReader = new cStartmenuReader();
            m_RootStartMenuItem = new cStartmenuItem();
            m_SearchResult = new cStartmenuItem();

            if (m_StartMenuReader != null)
            {
                //Read the Startmenu and give the RootItem as Object
                m_RootStartMenuItem = m_StartMenuReader.Load();
                m_StartMenuReader.UpdateMenuItems += _StartMenuReader_UpdateMenuItems;

                m_CurrentVisibleProgrammItems = new Dictionary<int, cStartmenuItem>();

            }

        }

        void _StartMenuReader_UpdateMenuItems(object sender, EventArgs e)
        {
            //m_Timer.Start();
            m_RootStartMenuItem = m_StartMenuReader.StartMenuRootItem;

        }

        public cStartmenuItem RootStartMenuItem
        {
            get { return (cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"]; }
        }

        public cStartmenuItem SearchResult
        {
            get { return m_SearchResult;  }
        }

        /// <summary>
        /// Activates the Usercontrol to show Computers startmenu and set the root startmenu item active
        /// </summary>
        public void Activate()
        {
            m_RootStartMenuItem = m_StartMenuReader.StartMenuRootItem;

            if (m_StartMenuRenderer == null)
            {
                m_StartMenuRenderer = new ItemRenderer(null, lbPrograms, (cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"]);
                m_StartMenuRenderer.CanAddToFavorites = true;
                m_StartMenuRenderer.SelectionChanged += _StartMenuRenderer_SelectionChanged;
                m_StartMenuRenderer.SetBreadCrumb += _StartMenuRenderer_SetBreadCrumb;
                m_StartMenuRenderer.AddFavorite += _StartMenuRenderer_AddFavorite;

                m_StartMenuRenderer.RenderItems((cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"]);
            }
            if (m_StartMenuRenderer != null && m_RootStartMenuItem != null && (cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"] != null)
                m_StartMenuRenderer.GoLevelUp((cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"]);
        }

        public cStartmenuItem SearchItems(string Match)
        {
            try
            {
                m_SearchResult = new cStartmenuItem();
                RecursiveItemSearch((cStartmenuItem)m_RootStartMenuItem.ChildItems["PROGRAMS"], Match);
                return  m_SearchResult;
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("Can't search !", ex, true, EMessageTypes.Error);
                return null;
            }
        }

        void ucStartmenuPrograms_Loaded(object sender, RoutedEventArgs e)
        {

        }

        void RecursiveItemSearch(cStartmenuItem Item, string Pattern)
        {
            Dictionary<string, object>.KeyCollection ChildItems = Item.ChildItems.Keys;
            foreach (string ItemKey in ChildItems)
            {
                if (((cStartmenuItem)Item.ChildItems[ItemKey]).ItemType == eItemType.Link)
                {
                    if (((cStartmenuItem)Item.ChildItems[ItemKey]).ViewName.ToUpper().Contains(Pattern.ToUpper()) == true)
                        m_SearchResult.AddChild(((cStartmenuItem)Item.ChildItems[ItemKey]));
                } else if (((cStartmenuItem)Item.ChildItems[ItemKey]).ItemType == eItemType.Folder ||
                           ((cStartmenuItem)Item.ChildItems[ItemKey]).ItemType == eItemType.None)
                {
                    RecursiveItemSearch((cStartmenuItem)Item.ChildItems[ItemKey], Pattern);
                } 
            }
        }
        
        void _StartMenuRenderer_AddFavorite(string File, int LinkType)
        {
            if (this.AddFavorite != null) this.AddFavorite(File, LinkType);
        }

        void _StartMenuRenderer_SetBreadCrumb(object Sender, List<string> ItemNames, List<cStartmenuItem> Items)
        {
            try
            {

                if (_CanSelectStartMenuItem == true && ItemNames != null)
                {
                    StackPanel myStackpanel = new StackPanel();

                    string myBreadCrumbPart = "";
                    m_BreadCrumbItems = Items;

                    for (Int32 Index = Items.Count - 1; Index >= 0; Index--)
                    {
                        myBreadCrumbPart = Items[Index].ViewName;
                        if (Index > 0)
                        {
                            myBreadCrumbPart += "   >";
                        }

                        if (Index == 0)
                        {
                            System.Windows.Controls.Label myLinkLabel = new System.Windows.Controls.Label();
                            myLinkLabel.Content = myBreadCrumbPart;
                            myLinkLabel.Name = "Breakcrumb_" + Items[Index].ItemName;

                            myLinkLabel.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
                            myStackpanel.Children.Add(myLinkLabel);
                        }
                        else
                        {
                            ThemedControlsLibrary.LinkLabel myLinkLabel = new ThemedControlsLibrary.LinkLabel();
                            myLinkLabel.Content = myBreadCrumbPart;
                            myLinkLabel.Name = "Breakcrumb_" + Items[Index].ItemName;

                            myLinkLabel.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
                            myLinkLabel.Foreground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
                            myLinkLabel.HoverForeground = new SolidColorBrush(Color.FromRgb(0, 0, 0));
                            myLinkLabel.LinkLabelBehavior = ThemedControlsLibrary.LinkLabelBehavior.NeverUnderline;
                            myLinkLabel.Click += BreadCrumbItem_Click;
                            //myLabel.Width = 
                            myStackpanel.Children.Add(myLinkLabel);
                        }


                    }                    

                    myStackpanel.Height = 25;
                    myStackpanel.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
                    myStackpanel.Orientation = Orientation.Horizontal;

                    lblParentProgramsPath.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
                    lblParentProgramsPath.Content = myStackpanel;
                }
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("Can't set StartMenu - Path!", ex, true, EMessageTypes.Error);
            }
        }

        void BreadCrumbItem_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (m_StartMenuRenderer != null)
                {
                    if (m_BreadCrumbItems != null)
                    {
                        foreach (cStartmenuItem Item in m_BreadCrumbItems)
                        {
                            if (("Breakcrumb_" + Item.ItemName) == ((ThemedControlsLibrary.LinkLabel)sender).Name)
                            {
                                m_StartMenuRenderer.GoLevelUp(Item);
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("The selected Menu can't activate!", ex, true, EMessageTypes.Error);
            }
        }

        void _StartMenuRenderer_SelectionChanged(object Sender, cStartmenuItem Item)
        {
            try
            {
                
                if (Item != null)
                {
                    if (Item.ItemType == eItemType.Link)
                    {

                        System.Diagnostics.Debug.Print("Execute: '" + Item.LinkFilename + "'");
                        System.Diagnostics.Debug.Print("Execute arguments:'" + Item.Arguments + "'");
                        System.Diagnostics.Debug.Print("Execute workingdir:'" + Item.WorkingDirectory + "'");
                        long myShellExecReturn = WMSSoft.Lib.Shell.ShellAPI.ShellExecute(0, null, Item.ItemName, "", "", 1);

                        if (!(myShellExecReturn == (int)WMSSoft.Lib.Shell.EShellExecReturns.SE_RUNNING))
                        {
                            CMessagelogging.AppendMessage("Running selected Startmenuitem '" + Item.LinkFilename + "' failed! Return Message: '" +
                                                          WMSSoft.Lib.Shell.Shell_helpers.GetShellExecuteReturnMsg((WMSSoft.Lib.Shell.EShellExecReturns)myShellExecReturn) + "'",
                                                          null, true, EMessageTypes.Error);
                        }

                        System.Diagnostics.Debug.Print("Execute return: " + myShellExecReturn.ToString() + ";");

                    }
                }
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("The selected link can't be run!", ex, true, EMessageTypes.Error);
            }
        }

        /// <summary>
        /// Is used, if the user has been changed the selected item in programs listview
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void lbPrograms_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            try
            {
                if (m_CurrentVisibleProgrammItems.ContainsKey(lbPrograms.SelectedIndex) == true )
                {
                    if (m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].ItemType == eItemType.Link)
                    {                        
                        CMessagelogging.AppendMessage("Execute: '" + m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].LinkFilename + "'", 
                                                      null, false, EMessageTypes.Debug);
                        CMessagelogging.AppendMessage("Execute arguments:'" + m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].Arguments + "'",
                                                      null, false, EMessageTypes.Debug);
                        CMessagelogging.AppendMessage("Execute workingdir:'" + m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].WorkingDirectory + "'",
                                                      null, false, EMessageTypes.Debug);                        
                        //Let the shell execute the command/link
                        long myShellExecReturn = WMSSoft.Lib.Shell.ShellAPI.ShellExecute(0, null, m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].ItemName, "", "", 1);
                        //write the shellexecute returnvalue to log                        
                        CMessagelogging.AppendMessage("Execute return: " + myShellExecReturn.ToString() + ";",
                                                      null, false, EMessageTypes.Debug);

                        m_CurrentRootItem = m_ProgramStartMenuItem;
                        WriteStartmenuToListView();
                    }
                    else if (m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex].ItemType == eItemType.Folder)
                    {
                        //btnFolderUp.isEnabled = true;
                        m_CurrentRootItem = m_CurrentVisibleProgrammItems[lbPrograms.SelectedIndex];
                        WriteStartmenuToListView();
                    }
                }
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("The selected link can't be run!", ex, true, EMessageTypes.Error);
            }
        }

        void btnFolderUp_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                //Go a Folder up
                if (m_StartMenuRenderer != null)
                {
                    m_StartMenuRenderer.GoLevelUp();
                }
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("Can't go a Folder up!", ex, true, EMessageTypes.Error);
            }
        }
        /// <summary>
        /// Is used to view the current selected startmenu folder in programs tab
        /// </summary>
        void WriteStartmenuToListView()
        {
            try
            {
                //delete all programitems from dictionary and fill with new
                m_CurrentVisibleProgrammItems.Clear();
                lbPrograms.Items.Clear();

                if (m_CurrentRootItem != null)
                {                 
                    List<string> myFolderItems = m_CurrentRootItem.FolderItemKeys;
                    List<string> myLinkItems = m_CurrentRootItem.LinkItemList;

                    //lblProgramsMenuPath.Content = _CurrentRootItem.FolderMenuPath;

                    //add folders to listview               
                    foreach (string SubItem in myFolderItems)
                    {

                        AddItemToListBox((cStartmenuItem)m_CurrentRootItem.ChildItems[SubItem], lbPrograms, m_CurrentVisibleProgrammItems);
                    }

                    //add links to listview
                    foreach (string SubItem in myLinkItems)
                    {
                        AddItemToListBox((cStartmenuItem)m_CurrentRootItem.ChildItems[SubItem], lbPrograms, m_CurrentVisibleProgrammItems);
                    }
                }
            }
            catch (Exception Ex)
            {
                CMessagelogging.AppendMessage("Unable to write StartMenu to Listbox!", Ex, true, EMessageTypes.Error);
            }
        }
        int AddItemToListBox(cStartmenuItem SubItem, ListBox Box, Dictionary<int, cStartmenuItem> VProgramItems)
        {
            try
            {
                if (SubItem != null)
                {
                    int iNewItemIndex = -1;

                    //iNewItemIndex = lbPrograms.Items.Add(mySubItem.ItemName);

                    StackPanel myStackpanel = new StackPanel();
                    TextBlock myTextblock = new TextBlock();

                    //only a image is available we can add this
                    if (SubItem.Image != null)
                    {
                        Image myImage = new Image();
                        myImage.Height = 32;
                        myImage.Width = 32;
                        myImage.Source = SubItem.Image;
                        myImage.Margin = new Thickness(5.0, 0.0, 0.0, 0.0);
                        myStackpanel.Children.Add(myImage);
                    }

                    myTextblock.TextAlignment = SubItem.TextAlign; // TextAlignment.Left;
                    myTextblock.Text = SubItem.ViewName;
                    myTextblock.FontFamily = new System.Windows.Media.FontFamily(SubItem.FontName);
                    myTextblock.FontSize = SubItem.FontSize; // 12;
                    myTextblock.Foreground = new SolidColorBrush(SubItem.FontColor);
                    myTextblock.VerticalAlignment = SubItem.VerticalAlign; // System.Windows.VerticalAlignment.Center;
                    myTextblock.Padding = new Thickness(5.0, 0.0, 0.0, 0.0);

                    myStackpanel.Children.Add(myTextblock);
                    myStackpanel.Height = SubItem.ItemHeight;
                    myStackpanel.Orientation = Orientation.Horizontal;

                    ListBoxItem myListItem = new ListBoxItem();
                    myListItem.Content = myStackpanel;
                    iNewItemIndex = Box.Items.Add(myListItem);

                    if (iNewItemIndex >= 0 && iNewItemIndex < Box.Items.Count)
                    {
                        //add this item to programitem list
                        if (VProgramItems.ContainsKey(iNewItemIndex) == false)
                        {
                            VProgramItems.Add(iNewItemIndex, SubItem);
                        }
                    }
                    return iNewItemIndex;
                } return -1;
            }
            catch (Exception ex)
            {
                CMessagelogging.AppendMessage("Error while adding startmenuitem to listview!", ex, true, EMessageTypes.Error);
                return -1;
            }
        }

        private void lbPrograms_MouseDown(object sender, MouseButtonEventArgs e)
        {
            
            if (e.ChangedButton == MouseButton.Left)
            {
            }
        }

 
        
    }
}
